package logic

import (
	"errors"
	"excel/dao/mysql"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/xuri/excelize/v2"
	"go.uber.org/zap"
)

func GenerateExcel(Filename string) error {
	Filename = "新" + Filename // 确保文件名正确

	// 从数据库获取活动数据
	activities, err := mysql.GetActivitiesFromDatabase()
	if err != nil {
		fmt.Println("Error fetching activities from database:", err)
		return err
	}

	// 从模板文件加载 Excel
	f, err := excelize.OpenFile("./upload/data.xlsx")
	if err != nil {
		fmt.Println("Error opening template file:", err)
		return err
	}

	// 定义工作表名
	sheetName := "Sheet0"
	index, _ := f.GetSheetIndex(sheetName) // 获取活动工作表的索引
	if index == -1 {
		fmt.Println("Sheet not found:", sheetName)
		return fmt.Errorf("工作表未找到: %s", sheetName)
	}

	// 填充活动数据
	for rowIndex, activity := range activities {
		row := []interface{}{
			activity.Title, activity.Manager, activity.Mobile,
			activity.ActiveBeginDate, activity.ActiveEndDate,
			activity.StartDate, activity.EndDate,
			activity.Type, activity.Form, activity.ServiceObject,
			activity.Content, activity.Street,
			activity.Neighborhood, activity.Address,
			activity.Total, activity.MinNum,
			activity.Organizer, activity.VolunteerLeader,
			activity.VolLeaderTel, activity.VolunteerNum,
			activity.VolunteerOrganizer, activity.Join,
			activity.PublicizeVolunteers, activity.Status,
			activity.PracticeVolunteers, activity.Persons,
			activity.Num,
		}
		for colIndex, value := range row {
			cell, err := excelize.CoordinatesToCellName(colIndex+1, rowIndex+3) // 从第三行开始写入数据
			if err != nil {
				fmt.Println("Error generating cell name:", err)
				return err
			}
			if err := f.SetCellValue(sheetName, cell, value); err != nil {
				fmt.Println("Error setting activity data:", err)
				return err
			}
		}
	}

	// 设置工作表为活动工作表
	f.SetActiveSheet(index)

	// 定义输出路径
	outputPath := "./upload/" + Filename
	// 保存文件
	if err := f.SaveAs(outputPath); err != nil {
		fmt.Println("Error saving Excel file:", err)
		return err
	}

	//fmt.Println("Excel 文件已成功创建！")
	return nil
}

func CleanTitle(title string) string {
	keywords := []string{"社区", "街道", "实践站", "开展"} // 需要去掉的关键词
	for _, keyword := range keywords {            // 遍历每个关键词
		if index := strings.Index(title, keyword); index != -1 { // 找到第一个匹配的关键词位置
			title = title[index+len(keyword):] // 删除关键词及其之前的内容
			break                              // 只删除一次，跳出循环
		}
	}
	return strings.TrimSpace(title) // 返回处理后的标题，并去掉前后多余的空格
}

func NormalizeDate(dateStr string) (string, error) {
	dateStr = strings.ReplaceAll(dateStr, " ", "")
	dateStr = strings.ReplaceAll(dateStr, "：", ":")
	dateStr = strings.ReplaceAll(dateStr, "\n", "")
	dateStr = strings.ReplaceAll(dateStr, "\r", "")
	dateStr = strings.ReplaceAll(dateStr, "\u0000", "")
	dateStr = strings.ReplaceAll(dateStr, "点半", ":30")
	dateStr = strings.ReplaceAll(dateStr, "点", ":00")
	dateStr = strings.ReplaceAll(dateStr, "上午", " ")
	dateStr = strings.ReplaceAll(dateStr, "下午", " ")
	dateStr = strings.ReplaceAll(dateStr, "上", " ")
	dateStr = strings.ReplaceAll(dateStr, "下", " ")
	dateStr = strings.ReplaceAll(dateStr, "午", " ")

	// 如果没有年份，默认年份为2024
	if !strings.Contains(dateStr, "年") && !strings.Contains(dateStr, ".") {
		dateStr = "2024年" + dateStr
	}

	// 正则表达式匹配日期时间格式
	re := regexp.MustCompile(`(\d{4})[.\-](\d{1,2})[.\-](\d{1,2}) (\d{1,2}):(\d{2})`)
	matches := re.FindStringSubmatch(dateStr)

	if len(matches) == 6 {
		year, _ := strconv.Atoi(matches[1])
		month, _ := strconv.Atoi(matches[2])
		day, _ := strconv.Atoi(matches[3])
		hour, _ := strconv.Atoi(matches[4])
		minute, _ := strconv.Atoi(matches[5])

		// 创建时间对象
		t := time.Date(year, time.Month(month), day, hour, minute, 0, 0, time.Local)
		return fmt.Sprintf("%d年%d月%d日%d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()), nil
	}

	// 处理原有的“年、月、日”格式
	reOld := regexp.MustCompile(`(\d+)年(\d+)月(\d+)日(\d+):(\d+)`)
	matchesOld := reOld.FindStringSubmatch(dateStr)
	if len(matchesOld) != 6 {
		return "", fmt.Errorf("时间格式错误: 未匹配到正确格式, 原始数据: %s", dateStr)
	}

	year, _ := strconv.Atoi(matchesOld[1])
	month, _ := strconv.Atoi(matchesOld[2])
	day, _ := strconv.Atoi(matchesOld[3])
	hour, _ := strconv.Atoi(matchesOld[4])
	minute, _ := strconv.Atoi(matchesOld[5])

	// 创建时间对象
	t := time.Date(year, time.Month(month), day, hour, minute, 0, 0, time.Local)

	return fmt.Sprintf("%d年%d月%d日%d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()), nil
}

// ValidateDateOrder 校验时间顺序
func ValidateDateOrder(activity *mysql.Activity) bool {
	layout := "2006年1月2日15:04"
	abd, err := time.Parse(layout, activity.ActiveBeginDate)
	if err != nil {
		zap.L().Error("时间解析失败", zap.Error(err))
		return false
	}
	sd, err := time.Parse(layout, activity.StartDate)
	if err != nil {
		zap.L().Error("时间解析失败", zap.Error(err))
		return false
	}
	ed, err := time.Parse(layout, activity.EndDate)
	if err != nil {
		zap.L().Error("时间解析失败", zap.Error(err))
		return false
	}
	aed, err := time.Parse(layout, activity.ActiveEndDate)
	if err != nil {
		zap.L().Error("时间解析失败", zap.Error(err))
		return false
	}

	// 检查时间顺序，允许相等
	if sd.After(abd) {
		zap.L().Error("报名开始时间比活动开始时间晚，已调整",
			zap.String("原始报名开始时间", activity.StartDate),
			zap.String("调整后的报名开始时间", activity.ActiveBeginDate))
		activity.StartDate = activity.ActiveBeginDate
	}

	if ed.After(aed) {
		zap.L().Error("报名结束时间比活动结束时间晚，已调整",
			zap.String("原始报名结束时间", activity.EndDate),
			zap.String("调整后的报名结束时间", activity.ActiveEndDate))
		activity.EndDate = activity.ActiveEndDate
	}
	return true
}

// normalizeActivityType 规范化活动类型
func NormalizeActivityType(activityType string) (string, error) {
	// 原有的映射逻辑
	validTypes := map[string]string{
		"理论政策宣讲": "理论政策宣讲",
		"教育服务":   "教育服务",
		"文化服务":   "文化服务",
		"科技科普服务": "科技科普服务",
		"健康健身服务": "健康健身服务",
		"其他":     "其他",
		"市民":     "其他",
		"理论宣讲":   "理论政策宣讲",
		"理论政策":   "理论政策宣讲",
		"科技科普":   "科技科普服务",
		"科学普及":   "科技科普服务",
		"科普宣传":   "科技科普服务",
		"科技普及":   "科技科普服务",
		"科普":     "科技科普服务",
		"文化":     "文化服务",
		"教育":     "教育服务",
		"健康":     "健康健身服务",
		"健康活动":   "健康健身服务",
		"市民教育":   "教育服务",
		"文化活动":   "文化服务",
		"健身活动":   "健康健身服务",
		"健身":     "健康健身服务",
		"体育健身":   "健康健身服务",
	}
	// 检查关键词
	if strings.Contains(activityType, "理论") || strings.Contains(activityType, "政策") {
		return "理论政策宣讲", nil
	}
	if strings.Contains(activityType, "科技") {
		return "科技科普服务", nil
	}
	if strings.Contains(activityType, "教育") {
		return "教育服务", nil
	}
	if strings.Contains(activityType, "体育") {
		return "健康健身服务", nil
	}
	if strings.Contains(activityType, "健康") {
		return "健康健身服务", nil
	}
	if strings.Contains(activityType, "科普") {
		return "科技科普服务", nil
	}
	// 使用原有的映射逻辑
	if val, exists := validTypes[activityType]; exists {
		return val, nil
	} else {
		return "", fmt.Errorf("活动类型不合法: %s", activityType)
	}
}

func CleanOrganizer(organizer string, street *string, neighborhood *string) (string, error) {
	// 若承办单位为空，则根据社区生成默认值
	if organizer == "" {
		if *neighborhood == "" {
			return "", errors.New("承办单位为空时，社区(neighborhood)不能为空")
		}
		organizer = fmt.Sprintf("%s新时代文明实践站", *neighborhood)
	}

	// 若同时包含 "社区" 和 "街道"，去掉开头的 "街道" 及之前的内容
	if strings.Contains(organizer, "社区") && strings.Contains(organizer, "街道") {
		// 找到最后一个 "街道" 的位置
		lastJieDaoIndex := strings.LastIndex(organizer, "街道")
		if lastJieDaoIndex >= 0 {
			// 去掉 "街道" 及之前的内容
			organizer = organizer[lastJieDaoIndex+len("街道"):]
		}
	}

	// 根据承办单位后缀处理所属街道和社区的必填情况
	if strings.HasSuffix(organizer, "实践站") {
		if *street == "" || *neighborhood == "" {
			return "", errors.New("承办单位为实践站，街道和社区必须有值")
		}
	} else if strings.HasSuffix(organizer, "实践所") {
		if *street == "" {
			return "", errors.New("承办单位为实践所，街道必须有值")
		}
		// 所属社区可以为空
	} else if strings.HasSuffix(organizer, "实践中心") {
		// 所属街道和社区可以为空
	}

	// 检查承办单位格式是否符合要求
	if !IsValidOrganizerFormat(organizer) {
		return "", errors.New("承办单位格式不符合要求")
	}

	return organizer, nil
}

// IsValidOrganizerFormat 检查承办单位格式是否符合要求
func IsValidOrganizerFormat(organizer string) bool {
	// 去掉空格和换行符
	organizer = strings.ReplaceAll(organizer, " ", "")
	organizer = strings.ReplaceAll(organizer, "\n", "")
	organizer = strings.ReplaceAll(organizer, "\r", "")

	// 承办单位应符合 XXX街道新时代文明实践所 或 XX社区新时代文明实践站
	if strings.HasSuffix(organizer, "新时代文明实践所") ||
		strings.HasSuffix(organizer, "新时代文明实践站") ||
		strings.HasSuffix(organizer, "新时代文明实践中心") {
		return true
	}
	return false
}

func ParseVolunteerCount(countStr string) (int, error) {
	// 去除“人”字
	countStr = strings.ReplaceAll(countStr, "人", "")
	// 转换为整数
	count, err := strconv.Atoi(strings.TrimSpace(countStr))
	if err != nil {
		return 0, fmt.Errorf("转换失败: %v", err)
	}
	return count, nil
}
func ParseVolunteerCountString(countStr string) (string, error) {
	// 去除“人”字
	countStr = strings.ReplaceAll(countStr, "人", "")
	// 转换为整数
	count, err := strconv.Atoi(strings.TrimSpace(countStr))
	if err != nil {
		return "", fmt.Errorf("转换失败: %v", err)
	}

	// 如果数字为零，返回空字符串
	if count == 0 {
		return "", nil
	}

	// 返回数字的字符串形式
	return strconv.Itoa(count), nil
}
